Vue.directive('demo', {
    bind() {

    },
    inserted() {

    },
    update() {

    }
})






export default function directive(app) {
    app.directive('demo', {
        // 相当于bind
        beforeMount() {

        },
        // 相当于inserted
        mounted() {

        },
        beforeUpdate() {

        },
        updated() {

        },
        beforeUnmount() {

        },
        unmounted() {

        }
    })
}



import Vue from 'vue'
(function () {
    Vue.directive('copy', {
        bind(el, binding) {
            el.$value = binding.value
            el.$handle = function () {
                let text = el.$value
                if (!text) {
                    console.log('剪切板内容为空')
                    return
                }
                let textarea = document.createElement('textarea')
                textarea.value = text
                textarea.readOnly = 'readonly'
                textarea.style.cssText = 'opacity:0;positon:fixed;left:-9999px'
                document.body.appendChild(textarea)
                textarea.select()
                let copyText = document.execCommand('Copy')
                if (copyText) {
                    console.log('内容已经复制到剪切板')
                }
                document.body.removeChild(textarea)
            }
            el.addEventListener('click', el.$handle)
        },
        componentUpdated(el, binding) {
            el.$value = binding.value
        },
        unbind(el, binding) {
            el.removeEventListener('click', el.$handle)
        }
    })

    const trigger = function trigger(el, type) {
        let ev = document.createEvent('HTMLEvents')
        ev.initEvent(type, true, true)
        ev.dispatchEvent(ev)
    }
    Vue.directive('emoji', {
        bind(el, binding) {
            el.$handle = function () {
                let value = el.value,
                    reg = /[^0-9a-zA-Z]/g;
                el.value = value.replace(reg, '')
                trigger(el, 'input')
            }
            el.addEventListener('keyup', el.$handle)
        },
        unbind(el) {
            el.removeEventListener('keyup', el.$handle)
        }
    })

    /**
     * 方式1：
     * v-debonce:[wait].immediate="{
     *  func: fn,
     *  type: 'click',
     *  prams: [10, 20]
     * }"
     */
    /**
     * 方式2：
     * v-debonce="fn"
     */
    function debounce(fn, wait, immediate = false) {
        let self = this,
            timer = null;
        return function () {
            let exec = immediate && !timer;
            clearTimeout(timer);
            timer = setTimeout(() => {
                clearTimeout(timer);
                timer = null;
                !immediate && fn.call(self);
            }, wait)
            exec ? fn.call(self) : null
        }
    }
    function throttle(func, wait) {
        if (typeof func !== "function") throw new TypeError("func must be an function!");
        if (typeof wait === "undefined") wait = 500;

        let timer = null, previous = 0;
        return function proxy(...args) {
            let now = new Date(),
                remaining = wait - (now - previous),
                self = this;
            if (remaining <= 0) {
                clearTimeout(timer);
                timer = null;
                previous = now;
                func.call(self, ...args);
            }
            if (!timer) {
                timer = setTimeout(function () {
                    clearTimeout(timer);
                    timer = null;
                    previous = +new Date();
                    func.call(self, ...args)
                }, remaining)
            }
        }
    }
    Vue.directive('debonce', {
        bind(el, binding) {
            let val = binding.value, wait = 500, type = 'click', prams = [], immediate = false, func = function () { }, handle = binding.name === 'debounce' ? debounce : throttle
            if (val === null) return
            if (typeof val !== 'object' && typeof val !== 'function') return
            if (binding.arg) wait = +binding.arg
            if (binding.modifiers && binding.modifiers.immediate) immediate = true
            if (typeof val === 'function') func = val
            if (typeof val === 'object') {
                ({
                    func,
                    type,
                    prams
                } = val)
            }
            el.$type = type
            el.$handle = handle(function (...args) {
                return func.call(this, ...prams.concat(args))
            }, wait, immediate)
            el.addEventListener(el.$type, el.$handle)
        },
        unbind(el, binding) {
            el.removeEventListener(el.$type, el.$handle)
        }
    })


    const ob_config = {
        threshold: [1]
    }
    const ob = new IntersectionObserver((entries) => {
        entries.forEach(item => {
            let {
                target,
                isIntersecting
            } = item
            if(!isIntersecting) return
            let imgBox = target.querySelector('img')
            if(!imgBox) return
            imgBox.src = target.src
            imgBox.style.opacity = 1
            ob.unobserve(target)
        })
    }, ob_config)
    Vue.directive('lazyload', {
        inserted(el, binding) {
            let imgBox = el.querySelector('img')
            if(!imgBox) return
            imgBox.src = ''
            imgBox.style.opacity = 0
            imgBox.style.transition = 'opacity .3s'
            el.$src = binding.value
            ob.observe(el)
        }
    })
})()